/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __CONFLICT_DECLARATION_HDR__
#define __CONFLICT_DECLARATION_HDR__


#ifdef WIN32
	#pragma warning(disable:4503)		// disable - decorated name length exceeded
	#pragma warning(disable:4786)		// disable 'identifier' truncation warning
#endif


#include <limits>
#include <map>
#include <set>
#include <string>


#define CONFLICTAIRCRAFT       std::pair<std::string, std::string>
#define CONFLICTDECLARATIONMAP std::map<CONFLICTAIRCRAFT, ConflictDeclaration>


namespace atc 
{
	const int CONFLICT_DECLARATION_THRESHOLD = 30;	// Time (in secs) where a participant
													// must declare a conflict before 
													// a target pair's final time

	class ConflictDeclaration 
	{
		friend class ConflictDeclarationBuilder;

	public:
		enum ConflictType
		{
			CONFLICT_TYPE_UNKNOWN,
			CONFLICT_TYPE_CONFLICT,
			CONFLICT_TYPE_NON_CONFLICT
		};

		enum ActionType
		{
			NO_ACTION,
			ACTIONED_CONFLICT,
			ACTIONED_NON_CONFLICT,
			MISSED_CONFLICT,						// Missed due to response after final time
			ALREADY_CONFLICTED,						// Missed due to conflict already occurred
			MISSED_NON_CONFLICT,
			FALSE_ALARMED_CONFLICT_TARGET,
			FALSE_ALARMED_CONFLICT_NON_TARGET,
			FALSE_ALARMED_NON_CONFLICT_TARGET,
			FALSE_ALARMED_NON_CONFLICT_NON_TARGET
		};

		ConflictDeclaration(const ConflictDeclaration&);
		~ConflictDeclaration();
	
		CONFLICTAIRCRAFT conflict_pair() const;

		double			seperation()			const	{	return m_sep;				}
		ActionType		Action()				const	{	return m_action;			}
		ConflictType	Type()					const	{	return m_conflictType;		}
		long			FinalTime()				const	{	return m_finalTime;			}
		void			SetAction(ActionType a_type)	{	m_action = a_type;			}

		bool			ConflictDeclaredOnTime(long a_currentTime) const;

		static ConflictDeclaration 
		CreateFalseAlarmConflict(const std::string& a_ac0, const std::string& a_ac1) 
		{
			return ConflictDeclaration(	a_ac0, 
										a_ac1, 
										std::numeric_limits<double>::quiet_NaN(), 
										CONFLICT_TYPE_CONFLICT,
										0);
		}

		static ConflictDeclaration 
		CreateFalseAlarmNonConflict(const std::string& a_ac0, const std::string& a_ac1) 
		{
			return ConflictDeclaration(	a_ac0, 
										a_ac1, 
										std::numeric_limits<double>::quiet_NaN(), 
										CONFLICT_TYPE_NON_CONFLICT,
										0);
		}

	private:
		ConflictDeclaration(const std::string&	a_callsign1, 
							const std::string&	a_callsign2, 
							const double		a_separation,
							ConflictType		a_conflictType,
							const long			a_finalTime);

	private:
		const std::string	m_ac0;
		const std::string	m_ac1;
		double				m_sep;
		ConflictType		m_conflictType;
		long				m_finalTime;
		ActionType			m_action;
	};


	class ConflictDeclarationBuilder 
	{
	public:
		ConflictDeclarationBuilder* set_separation	(const double);
		ConflictDeclarationBuilder* add_aircraft	(const std::string &);
		ConflictDeclarationBuilder* SetConflictType	(ConflictDeclaration::ConflictType a_conflictType);
		ConflictDeclarationBuilder* SetFinalTime	(long a_finalTime);

		CONFLICTDECLARATIONMAP build();

	private:
		double					m_separation;
		ConflictDeclaration::ConflictType			m_conflictType;
		long					m_finalTime;
		std::set<std::string>	m_callsigns;
	};


	typedef CONFLICTAIRCRAFT       ConflictAircraftPair;
	typedef CONFLICTDECLARATIONMAP ConflictDeclarationMap;

};

#undef CONFLICTDECLARATIONMAP
#undef CONFLICTAIRCRAFT

#endif
